package com.beikai.mybatisplus.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.beikai.mybatisplus.user.mapper.UserMapper;
import com.beikai.mybatisplus.user.model.UserModel;
import com.beikai.mybatisplus.user.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author beikai
 * @since 2019-06-15
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, UserModel> implements IUserService {

    @Override
    public List<UserModel> getAllUser1() {
        log.info("getAllUser1  --> 开始");
        List<UserModel> list = list();
        log.info("getAllUser1  --> 结束");
        return list;
    }

    @Override
    public List<UserModel> getAllUser2() {
        log.info("getAllUser2  --> 开始");
        List<UserModel> list = list(new QueryWrapper<UserModel>());
        log.info("getAllUser2  --> 结束");
        return list;
    }

    @Override
    public List<UserModel> getAllUser3() {
        log.info("getAllUser3  --> 开始");
        List<UserModel> list = list(new QueryWrapper<UserModel>().lambda().select(UserModel::getId, UserModel::getAge, UserModel::getEmail, UserModel::getName));

        log.info("getAllUser3  --> 结束");
        return list;
    }

    @Override
    public UserModel getAllUserById1(Long id) {
        log.info("getAllUserById1  --> 开始");
        UserModel one = getOne(new QueryWrapper<UserModel>().lambda().eq(UserModel::getId, id));
        log.info("getAllUserById1  --> 结束");
        return one;
    }

    @Override
    public UserModel getAllUserById2(Long id) {
        log.info("getAllUserById2  --> 开始");
        UserModel one = getOne(new QueryWrapper<UserModel>().eq("id", id));
        log.info("getAllUserById2  --> 结束");
        return one;
    }

    @Override
    public UserModel getAllUserById3(Long id) {
        log.info("getAllUserById3  --> 开始");
        UserModel one = getOne(new QueryWrapper<UserModel>()
                .lambda()
                .select(UserModel::getId, UserModel::getAge, UserModel::getEmail, UserModel::getName)
                .eq(UserModel::getId, id));
        log.info("getAllUserById3  --> 结束");
        return one;
    }

    @Override
    public boolean add(UserModel userModel) {
        log.info("add1  --> 开始");
        boolean save = save(userModel);
        // 在添加后会 返回主键
        System.out.println(userModel.getId());
        log.info("add1  --> 结束");
        return save;
    }

    @Override
    public boolean add(String name, Integer age, String email) {
        log.info("add2  --> 开始");
        boolean save = save(new UserModel(name, age, email));
        log.info("add2  --> 结束");
        return save;
    }

    @Override
    public boolean addBatchUser(List<UserModel> userModels) {
        log.info("addBatchUser  --> 开始");
        boolean saveBatch = saveBatch(userModels);
        log.info("addBatchUser  --> 结束");
        return saveBatch;
    }

    @Override
    public boolean addBatchUserByNum(List<UserModel> userModels, Integer num) {
        log.info("addBatchUserByNum  --> 开始");
        boolean saveBatch = saveBatch(userModels, num);
        log.info("addBatchUserByNum  --> 结束");
        return saveBatch;
    }

    @Override
    public boolean addBatchUserOrUpdate(List<UserModel> userModels) {
        log.info("addBatchUserOrUpdate  --> 开始");
        boolean saveOrUpdateBatch = saveOrUpdateBatch(userModels);
        log.info("addBatchUserOrUpdate  --> 结束");
        return saveOrUpdateBatch;
    }

    @Override
    public boolean addBatchUserOrUpdateByNum(List<UserModel> userModels, Integer num) {
        log.info("addBatchUserOrUpdateByNum  --> 开始");
        boolean saveOrUpdateBatch = saveOrUpdateBatch(userModels, num);
        log.info("addBatchUserOrUpdateByNum  --> 结束");
        return saveOrUpdateBatch;
    }

    @Override
    public boolean addUserOrUpdate(UserModel userModels) {
        log.info("addUserOrUpdate  --> 开始");
        boolean saveOrUpdate = saveOrUpdate(userModels);
        log.info("addUserOrUpdate  --> 结束");
        return saveOrUpdate;
    }

    @Override
    public boolean removeByMap2(String name, Integer age, String email) {
        log.info("removeByMap2  --> 开始");
        Map<String, Object> params = getMaps(null, name, email, age);
        boolean removeByMap = removeByMap(params);
        log.info("removeByMap2  --> 结束");
        return removeByMap;
    }

    /**
     * 如果采用了 eq 的方式,则如果对应eq 中参数为null ,也会按照null 查, 所以使用这种方式,参数都要有的
     * DELETE
     * FROM
     * user
     * WHERE
     * email = 'jiashuai3@qq.com'
     * AND age = null
     * AND name = null
     *
     * @param name
     * @param age
     * @param email
     * @return
     */
    @Override
    public boolean removeByWrapper(String name, Integer age, String email) {
        log.info("removeByWrapper  --> 开始");
        boolean remove = remove(new QueryWrapper<UserModel>()
                .eq("email", email).eq("age", age).eq("name", name));
        log.info("removeByWrapper  --> 开始");
        return remove;
    }

    @Override
    public boolean myUpdate(UserModel userModel) {
        log.info("myUpdate  --> 开始");
        boolean update = update(new UpdateWrapper<UserModel>()
                .lambda()
                .set(UserModel::getName, userModel.getName())
                .eq(UserModel::getId, userModel.getId()));
        log.info("myUpdate  --> 结束");
        return update;
    }

    @Override
    public Collection<UserModel> getByMap(Long id, String name, String email, Integer age) {
        log.info("getByMap  --> 开始");
        Map<String, Object> params = getMaps(id, name, email, age);
        Collection<UserModel> userModels = listByMap(params);
        log.info("getByMap  --> 结束");
        return userModels;
    }

    private Map<String, Object> getMaps(Long id, String name, String email, Integer age) {
        Map<String, Object> params = new HashMap<>();
        if (StringUtils.isNotEmpty(name)) {
            params.put("name", name);
        }
        if (StringUtils.isNotEmpty(email)) {
            params.put("email", email);
        }
        if (null != age) {
            params.put("age", age);
        }
        if (null != id) {
            params.put("id", id);
        }
        return params;
    }

    @Override
    public List<Map<String, Object>> getByResultMap(String name, String email, Integer age, Long id) {
        log.info("getPageByMap  --> 开始");
        List<Map<String, Object>> maps = listMaps(new QueryWrapper<UserModel>()
                .lambda()
                .eq(UserModel::getAge, age)
                .eq(UserModel::getName, name)
                .eq(UserModel::getEmail, email));
        log.info("getPageByMap  --> 结束");
        return maps;
    }

    @Autowired
    private UserMapper userMapper;
    // 测试 mapper 接口

    /**
     * 插入数据
     *
     * @param userModel
     * @return
     */
    @Override
    public int insert(UserModel userModel) {
        return userMapper.insert(userModel);
    }

    ;

    /**
     * 通过id 删除记录
     *
     * @param id
     * @return
     */
    @Override
    public int deleteById(Long id) {
        return userMapper.deleteById(id);
    }

    /**
     * 通过 map 条件 删除记录
     *
     * @param id
     * @param name
     * @param email
     * @param age
     * @return
     */
    @Override
    public int deleteByMap(Long id, String name, String email, Integer age) {
        return userMapper.deleteByMap(getMaps(id, name, email, age));
    }

    /**
     * 通过制定条件 删除
     *
     * @param age
     * @return
     */
    @Override
    public int delete(Integer age) {
        return userMapper.delete(new QueryWrapper<UserModel>().lambda().eq(UserModel::getAge, age));
    }

    /**
     * 通过 id 集合 批量删除
     *
     * @param ids
     * @return
     */
    @Override
    public int deleteBatchIds(List<Long> ids) {
        return userMapper.deleteBatchIds(ids);
    }

    /**
     * 通过主键修改记录信息
     *
     * @param userModel
     * @return
     */
    @Override
    public int updateById2(UserModel userModel) {
        return userMapper.updateById(userModel);
    }

    /**
     * 设置制定条件 修改
     *
     * @param userModel
     * @return
     */
    @Override
    public int update2(UserModel userModel) {
        return userMapper.update(userModel, new UpdateWrapper<UserModel>()
                .lambda()
                .eq(UserModel::getId, userModel.getId()));


    }

    /**
     * 通过 id 获取记录
     *
     * @param id
     * @return
     */
    @Override
    public UserModel selectById(Long id) {
        return userMapper.selectById(id);
    }

    /**
     * 通过主键集合获取记录信息
     *
     * @param ids
     * @return
     */
    @Override
    public List<UserModel> selectBatchIds(List<Long> ids) {
        return userMapper.selectBatchIds(ids);
    }

    /**
     * 根据 map 参数 获取用户信息
     *
     * @param id
     * @param name
     * @param email
     * @param age
     * @return
     */
    @Override
    public List<UserModel> selectByMap(Long id, String name, String email, Integer age) {
        return userMapper.selectByMap(getMaps(id, name, email, age));
    }

    /**
     * 通过条件获取一条用户过记录
     *
     * @param id
     * @return
     */
    @Override
    public UserModel selectOne(Long id) {
        return userMapper.selectOne(new QueryWrapper<UserModel>().eq("id", id));
    }

    /**
     * 根据条件统计数量
     *
     * @param age
     * @return
     */
    @Override
    public Integer selectCount(Integer age) {
        return userMapper.selectCount(new QueryWrapper<UserModel>().eq("age", age));
    }

    /**
     * 通过 名字查询 用户记录  模糊搜索
     *
     * @param name
     * @return
     */
    @Override
    public List<UserModel> selectList(String name) {
        return userMapper.selectList(new QueryWrapper<UserModel>().lambda().likeRight(UserModel::getName, name));
    }

    /**
     * 通过名字查询 用户记录 模糊搜索 返回 map 类型集合
     *
     * @param name
     * @return
     */
    @Override
    public List<Map<String, Object>> selectMaps(String name) {
        return userMapper.selectMaps(new QueryWrapper<UserModel>().likeRight("name", name));
    }

    /**
     * 根据 wapper 条件,查询所有记录,
     *
     * @param name
     * @return
     */
    @Override
    public List<Object> selectObjs(String name) {
        return userMapper.selectObjs(new QueryWrapper<UserModel>().likeRight("name", name));
    }

    /**
     * 分页 获取 指定条件 记录信息
     *
     * @param pageNum
     * @param pageSize
     * @param name
     * @return
     */
    @Override
    public IPage<UserModel> selectPage(Integer pageNum, Integer pageSize, String name) {
        return userMapper.selectPage(new Page<>(pageNum, pageSize), new QueryWrapper<UserModel>()
                .likeRight("name", name));
    }

    /**
     * 通过条件返回map类型的信息,并分页
     *
     * @param pageNum
     * @param pageSize
     * @param name
     * @return
     */
    @Override
    public IPage<Map<String, Object>> selectMapsPage(Integer pageNum, Integer pageSize, String name) {
        return userMapper.selectMapsPage(new Page<>(pageNum, pageSize), new QueryWrapper<UserModel>()
                .likeRight("name", name));
    }

    @Override
    public boolean mydelete(Long id) {
        userMapper.myDelete2(new QueryWrapper<UserModel>().eq("id", id));
        return true;
    }

    @Override
    public List<UserModel> testAllEq(String name, String email, Integer age, Long id, Integer age2) {

        Map<String, Object> maps = getMaps(id, name, email, age);
        /**
         * eqall
         * 三个参数中, 第一个和第三个参数是 boolean 类型, 默认都为true并且不显示,
         *  第一个 boolean 为true时,以maps中的参数作为where 后面的条件,为false时 不以maps中的参数作为条件
         *  第二个 boolean 为true时,如果map中的value为null时 按照 isnull 查询,为false时, 不作为查询条件
         */
        List<UserModel> list = list(new QueryWrapper<UserModel>().allEq(true, maps, false));

        /**
         * ne  不等于
         *  ne("name", "老王")--->name <> '老王'
         *
         *
         */
        list = list(new QueryWrapper<UserModel>().ne(false, "name", name));
        /**
         * gt 大于
         *   gt("age", 18)--->age > 18
         */
        list = list(new QueryWrapper<UserModel>().gt(true, "age", age));
        /**
         * ge 大于等于
         */
        list = list(new QueryWrapper<UserModel>().ge("age", age));
        /**
         * lt 小于
         */
        list = list(new QueryWrapper<UserModel>().lt("age", age));
        /**
         * le 小于等于
         */
        list = list(new QueryWrapper<UserModel>().le("age", age));

        /**
         * between  两者之间
         */
        list = list(new QueryWrapper<UserModel>().between("age", age, age2));
        /**
         * notbetween  不在两者之间
         */
        list = list(new QueryWrapper<UserModel>().notBetween("age", age, age2));

        /**
         * like  模糊查询
         */
        list = list(new QueryWrapper<UserModel>().like("name", name));

        /**
         * likeRight  右侧有 % 的模糊查询
         */
        list = list(new QueryWrapper<UserModel>().likeRight("name", name));
        /**
         * likeLeft  左侧有 % 的模糊查询
         */
        list = list(new QueryWrapper<UserModel>().likeLeft("name", name));
        /**
         * notLike  notLike("name", "王")--->name not like '%王%'
         */
        list = list(new QueryWrapper<UserModel>().notLike("name", name));
        /**
         * isNull  isNull("name")--->name is null
         */
        list = list(new QueryWrapper<UserModel>().isNull("name"));
        /**
         * isNotNull  isNotNull("name")--->name is not null
         */
        list = list(new QueryWrapper<UserModel>().isNotNull("name"));

        return list;

    }

    @Override
    public List<UserModel> testAllEq2(List<Long> ids) {
        /**
         * in
         * in("age",{1,2,3})--->age in (1,2,3)
         */
        List<UserModel> list = list(new QueryWrapper<UserModel>().in("id", ids));
        /**
         * notin
         * notIn("age",{1,2,3})--->age not in (1,2,3)
         */
        list = list(new QueryWrapper<UserModel>().notIn("id", ids));

        /**
         * inSql
         * inSql("id", "select id from table where id < 3")--->id in (select id from table where id < 3)
         * 或
         * inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6)
         */
        list = list(new QueryWrapper<UserModel>().inSql("id", "select id from user where age < 24"));

        /**
         * notinSql
         * notInSql("id", "select id from table where id < 3")--->age not in (select id from table where id < 3)
         * 或
         * notInSql("age", "1,2,3,4,5,6")--->age not in (1,2,3,4,5,6)
         */
        list = list(new QueryWrapper<UserModel>().notInSql("id", "select id from user where age < 24"));
        /**
         * groupBy
         * groupBy("id", "name")--->group by id,name
         *
         *  如果有条件是重复的,第一个会被返回,第二个以后是不能返回的
         */
        list = list(new QueryWrapper<UserModel>().groupBy("name"));

        /**
         * orderByAsc
         *
         *  orderByAsc("id", "name")--->order by id ASC,name ASC
         *
         *  SELECT
         *         id,
         *         NAME,
         *         AGE,
         *         EMAIL
         *     FROM
         *         user
         *     ORDER BY
         *         age ASC
         *
         */
        list = list(new QueryWrapper<UserModel>().orderByAsc("age"));
        /**
         * orderByDesc
         * orderByDesc("id", "name")--->order by id DESC,name DESC
         *
         */
        /**
         * orderBy
         * orderBy(true, true, "id", "name")--->order by id ASC,name ASC
         *  第一个参数是 判断是否对应的条件生效
         *  第二个参数是 判断是否是asc 顺序排序
         *
         *   SELECT
         *         id,
         *         NAME,
         *         AGE,
         *         EMAIL
         *     FROM
         *         user
         *     ORDER BY
         *         age DESC
         */
        list = list(new QueryWrapper<UserModel>().orderBy(true, false, "age"));
        /**
         * having   同 group by 一同使用   having 可以包含聚合函数  如下 的sum()
         *  例 : having("sum(age) > 10")--->having sum(age) > 10
         * 例: having("sum(age) > {0}", 11)--->having sum(age) > 11
         *
         *  SELECT
         *         id,
         *         NAME,
         *         AGE,
         *         EMAIL
         *     FROM
         *         user
         *     GROUP BY
         *         name
         *     HAVING
         *         age > 23
         */
        list = list(new QueryWrapper<UserModel>().groupBy("name").having("age > 23 "));

        /**
         * or 方式一 : 拼接
         *              eq("id",1).or().eq("name","老王")--->id = 1 or name = '老王'
         * SELECT
         *         id,
         *         NAME,
         *         AGE,
         *         EMAIL
         *     FROM
         *         user
         *     WHERE
         *         name = '测试'
         *         OR age = 28
         *
         *    方式二 : 嵌套
         *              or(i -> i.eq("name", "李白").ne("status", "活着"))--->or (name = '李白' and status <> '活着')
         *      SELECT
         *         id,
         *         NAME,
         *         AGE,
         *         EMAIL
         *     FROM
         *         user
         *     WHERE
         *         name = '测试'
         *         OR (
         *             email = 'test2@baomidou.com'
         *             OR age >= 25
         *         )
         */
        list = list(new QueryWrapper<UserModel>().eq("name","测试").or().eq("age",28));
        list = list(new QueryWrapper<UserModel>()
                .eq("name","测试")
                .or(i -> i.eq("email","test2@baomidou.com").or().ge("age",25)));

        /**
         * and 嵌套
         *          and(i -> i.eq("name", "李白").ne("status", "活着"))--->and (name = '李白' and status <> '活着')
         *
         *  SELECT
         *         id,
         *         NAME,
         *         AGE,
         *         EMAIL
         *     FROM
         *         user
         *     WHERE
         *         name = '测试'
         *         AND (
         *             age = 18
         *         )
         */
        list = list(new QueryWrapper<UserModel>().eq("name","测试").and(i -> i.eq("age",18)));

        /**
         *  nested
         *      nested(i -> i.eq("name", "李白").ne("status", "活着"))--->(name = '李白' and status <> '活着')
         *
         *      SELECT
         *         id,
         *         NAME,
         *         AGE,
         *         EMAIL
         *     FROM
         *         user
         *     WHERE
         *         (
         *             name = '测试'
         *             AND age = '18'
         *         )
         */
        list = list(new QueryWrapper<UserModel>().nested(i -> i.eq("name","测试").eq("age","18")));

        /**
         * apply   可以 嵌入 sql 语句等
         *  该方法可用于数据库函数 动态入参的params对应前面applySql内部的{index}部分.这样是不会有sql注入风险的,反之会有!
         *
         *  例: apply("id = 1")--->id = 1
         * 例: apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
         * 例: apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
         *
         *      SELECT
         *         id,
         *         NAME,
         *         AGE,
         *         EMAIL
         *     FROM
         *         user
         *     WHERE
         *         create_time = date_format('2019-06-01 11:44:32','%Y-%m-%d %H:%i:%s')
         *         AND age = 28
         */
        list = list(new QueryWrapper<UserModel>().apply("create_time = date_format('2019-06-01 11:44:32','%Y-%m-%d %H:%i:%s')").eq("age",28));

        /**
         * last  无视优化规则 , 直接拼接 在 sql 语句后面
         *  last("limit 1")
         *
         *      SELECT
         *         id,
         *         NAME,
         *         AGE,
         *         EMAIL
         *     FROM
         *         user
         *     WHERE
         *         create_time = date_format('2019-06-01 11:44:32','%Y-%m-%d %H:%i:%s')
         *         AND age = 28 limit 1
         */
        list = list(new QueryWrapper<UserModel>().apply("create_time = date_format('2019-06-01 11:44:32','%Y-%m-%d %H:%i:%s')").eq("age",28).last("limit 1"));
        /**
         * exists
         *      拼接 exists
         *      exists("select id from table where age = 1")--->exists (select id from table where age = 1)
         *
         *  notExists
         *     拼接 not Exists
         *     notExists("select id from table where age = 1")--->not exists (select id from table where age = 1)
         */
        return list;
    }

    public IPage<UserModel> selectUserPage(Page<UserModel> page,Integer state){
        // 不进行 count sql 优化，解决 MP 无法自动优化 SQL 问题，这时候你需要自己查询 count 部分
        // page.setOptimizeCountSql(false);
        // 当 total 为非 0 时(默认为 0),分页插件不会进行 count 查询
        // 要点!! 分页返回的对象与传入的对象是同一个
        return userMapper.selectPageVo(page,state);
    }


}
